﻿using System;
using System.Drawing;
using System.Windows.Forms;
using CamOnWebController.Helper;
using CamOnWebController.Properties;

namespace CamOnWebController
{
    /// <summary>
    /// Classe de controle da WebCam.
    /// </summary>
    [ToolboxBitmap(typeof(Resources), "ToolbarIcon")]
    public partial class CamOnWebComponent : UserControl
    {
        // Altura e largura da imagem gerada pela WebCam
        private int m_Width = 500;
        private int m_Height = 500;

        //Handle da janela de controle da webcam.
        private int mCapHwnd;

        //Flag para verificar se webcam foi parada.
        private bool bStopped = true;

        /// <summary>
        /// Propriedade para manipulação de imagens.
        /// </summary>
        public PictureBox Imagem
        {
            get
            {
                return this.ImgWebCamShow;
            }

            set
            {
                this.ImgWebCamShow = value;
            }
        }

        /// <summary>
        /// Destrutor da classe.
        /// </summary>
        ~CamOnWebComponent()
        {
            this.Stop();
        }

        /// <summary>
        /// Construtor da classe.
        /// </summary>
        public CamOnWebComponent()
        {
            this.InitializeComponent();
        }

        #region Start and Stop Capture Functions

        /// <summary>
        /// Ajusta o tamanho da imagem da WebCam com o tamanho da tela.
        /// </summary>
        private void ImageSize()
        {
            this.m_Width = this.ImgWebCamShow.Size.Width;
            this.m_Height = this.ImgWebCamShow.Size.Height;
        }

        /// <summary>
        /// Iniciar a captura de telas da Webcam.
        /// </summary>
        public void Start()
        {
            try
            {
                //Ajusta o tamanho da imagem.
                this.ImageSize();

                // Por segurança, chamamos o método stop so para garantirmos que não estamos rodando o código.
                this.Stop();

                // Criamos a janela de captura usando a API "capCreateCaptureWindowA"
                mCapHwnd = User32.capCreateCaptureWindowA("WebCap", 0, 0, 0, this.m_Width, this.m_Height, this.Handle.ToInt32(), 0);

                // Liberamos recurso ao sistema operacional.
                Application.DoEvents();

                //Enviamos a mensagem através do SO para conectar com o driver da WebCam.
                User32.SendMessage(this.mCapHwnd, User32.WM_CAP_CONNECT, 0, 0);

                // Ajustamos o intervalo de captura da webcam.
                // Podemos aqui criar uma propriedade do componente para 
                // alterarmos o tempo. Lembrando que quanto maior o tempo 
                // maior o atraso entre o capturado e o exibido.
                this.tmrRefrashFrame.Interval = 1;
                this.bStopped = false;
                
                this.tmrRefrashFrame.Start();
            }
            catch (Exception excep)
            {
                MessageBox.Show("Ocorreu um erro na exibição da WebCam. Verifique se está tudo conectado.\r\n\n" + excep.Message);
                this.Stop();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Stop()
        {
            try
            {
                // stop the timer
                bStopped = true;
                this.tmrRefrashFrame.Stop();

                // Liberamos recurso ao sistema operacional.
                Application.DoEvents();

                //Envia mensagem ao SO para desconectar a Webcam.
                User32.SendMessage(this.mCapHwnd, User32.WM_CAP_DISCONNECT, 0, 0);

                //Fecha a área de transferência.
                User32.CloseClipboard();
            }
            catch
            { // Não dispara nenhum erro.
            }
        }
        #endregion

        #region Codigo de Captura de video.

        /// <summary>
        /// Captura os frames.
        /// </summary>
        private void tmrRefrashFrame_Tick(object sender, EventArgs e)
        {
            try
            {
                // Pausa o temporizador
                this.tmrRefrashFrame.Stop();

                //Ajusta o tamanho da imagem.
                this.ImageSize();

                // Envia ao SO a mensagem para capturar o próximo frame.
                User32.SendMessage(mCapHwnd, User32.WM_CAP_GET_FRAME, 0, 0);

                // copia o frame capturado para a área de transferência.
                User32.SendMessage(mCapHwnd, User32.WM_CAP_COPY, 0, 0);

                //Abre a área de transferência.
                User32.OpenClipboard(mCapHwnd);

                //Busca os dados da área de transferÊncia, colocando os dados em 
                //uma estrutura de ponteiro.
                IntPtr img = User32.GetClipboardData(2);

                //Fecha a área de transferÊncia.
                User32.CloseClipboard();

                //Criamos aqui um objeto do tipo Bitmap.
                System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(m_Width, m_Height);

                // System.Drawing.Bitmap bmp = aviHelper.Open("F:\\zzzteste.avi", 10, this.m_Width, this.m_Height);

                //Criamos um objeto gráfico para manipular nossa imagem.
                using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp))
                {
                    //Ajustamos algumas propriedades do nosso objeto gráfico.
                    //No caso abaixo, estou tentanto otimizar ao máximo a velocidade.
                    //Mas também a possível ajustar para a qualidade da imagem.
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
                    g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
                    g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;

                    //Pegamos a imagem que está na estrutura do ponteiro que buscamos da 
                    //área de transferÊncia e carregamos dentro do nosso bitmap.
                    g.DrawImage(Image.FromHbitmap(img), 0, 0, m_Width, m_Height);
                }

                //Exibimos o frame da Webcam no controle que adicionamos no formulário
                //o frame foi salvo na variável do tipo Bitmap
                //e será exibido no controle System.Windows.Forms.PictureBox abaixo.
                ImgWebCamShow.Image = bmp;

                

                //fazemos um refresh na imagem.
                ImgWebCamShow.Refresh();

                // Liberamos recurso ao sistema operacional.
                Application.DoEvents();

                if (!bStopped)
                {
                    this.tmrRefrashFrame.Start();
                }
            }
            catch (Exception excep)
            {
                MessageBox.Show("Ocorreu um erro na exibição da WebCam. Verifique se está tudo conectado.\r\n\n" + excep.Message);
                this.Stop(); // stop the process
            }
        }
        #endregion
    }
}